﻿//----------------------------------------------------------------
// <copyright file="MptInitializer.cs" company="Microsoft">
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// </copyright>
//----------------------------------------------------------------

using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using MptCodeLibrary.Configuration;
using MptCodeLibrary.Exceptions;
using MptCodeLibrary.TeamFoundation;

namespace MptCodeLibrary
{
    public class MptInitializer
    {
        private readonly IMptConfiguration mptConfiguration;
        private readonly ITeamFoundationFacade teamFoundationFacade;

        public const string ExpressionForWitTypeFilter = @"
(
    (
        (""ChangedFields/StringFields/Field[ReferenceName='Microsoft.VSTS.Common.WITCategory']/OldValue"" <> 'Value Proposition' AND ""ChangedFields/StringFields/Field[ReferenceName='Microsoft.VSTS.Common.WITCategory']/NewValue"" = 'Value Proposition')  
        OR (""ChangedFields/StringFields/Field[ReferenceName='Microsoft.VSTS.Common.WITCategory']/OldValue"" <> 'Feature Group' AND ""ChangedFields/StringFields/Field[ReferenceName='Microsoft.VSTS.Common.WITCategory']/NewValue"" = 'Feature Group')  
        OR (""ChangedFields/StringFields/Field[ReferenceName='Microsoft.VSTS.Common.WITCategory']/OldValue"" <> 'Feature' AND ""ChangedFields/StringFields/Field[ReferenceName='Microsoft.VSTS.Common.WITCategory']/NewValue"" = 'Feature')  
        OR (""ChangedFields/StringFields/Field[ReferenceName='Microsoft.VSTS.Common.WITCategory']/OldValue"" <> 'Deliverable' AND ""ChangedFields/StringFields/Field[ReferenceName='Microsoft.VSTS.Common.WITCategory']/NewValue"" = 'Deliverable') 
    )
    OR
    (
        ""ChangedFields/StringFields/Field[ReferenceName='System.Title']/NewValue"" <> 'null'
        AND
        (
{0}
        )
    )
) 
            "; 

        public MptInitializer(IMptConfiguration mptConfiguration, ITeamFoundationFacade teamFoundationFacade)
        {
            this.teamFoundationFacade = teamFoundationFacade;
            this.mptConfiguration = mptConfiguration;
        }

        public void SubscribeToEvents(string receiverPath)
        {
            IList<TeamServerConfiguration> tfsServers = (IList<TeamServerConfiguration>)mptConfiguration.TeamServers;

            if (tfsServers.Count == 0)
                throw new MptException(
                    "There aren't any TFS servers defined in the configuration file.  Update the config file and try again");

            StringBuilder filterExpression = new StringBuilder();
            IList<string> projectNames = CreateProjectNameClause(filterExpression);

            string workItemTypeClause = CreateWorkItemTypeClause(tfsServers, projectNames);

            filterExpression.AppendFormat(CultureInfo.InvariantCulture, ExpressionForWitTypeFilter, workItemTypeClause);

            foreach (TeamServerConfiguration tfsServer in tfsServers)
            {
                teamFoundationFacade.SignupForReceivingEvent(tfsServer.ServerName, receiverPath, filterExpression.ToString());
            }
        }

        private IList<string> CreateProjectNameClause(StringBuilder filterExpression)
        {
            IList<string> projectNames = (IList<string>)mptConfiguration.TeamProjects;
            if (projectNames.Count > 0)
            {
                filterExpression.Append("(");
                foreach (string projectName in projectNames)
                {
                    if (filterExpression.Length > 1)
                        filterExpression.Append(" OR ");

                    filterExpression.Append(string.Format(CultureInfo.InvariantCulture, "\"PortfolioProject\" = '{0}'",
                                                          projectName));
                }
                filterExpression.Append(") AND ");
            }
            return projectNames;
        }

        private string CreateWorkItemTypeClause(IEnumerable<TeamServerConfiguration> tfsServers, IEnumerable<string> projectNames)
        {
            var serversNames = from teamServerConfiguration in tfsServers
                               select teamServerConfiguration.ServerName;

            IEnumerable<string> workItemTypes = teamFoundationFacade.GetEventWorkItemTypesForProjects(serversNames,
                                                                                          projectNames);

            StringBuilder workItemtypeClause = new StringBuilder();

            foreach (string workItemType in workItemTypes)
            {
                if (workItemtypeClause.Length > 0)
                    workItemtypeClause.Append(" OR ");

                workItemtypeClause.AppendFormat(CultureInfo.InvariantCulture,
                                                @"""CoreFields/StringFields/Field[ReferenceName='System.WorkItemType']/NewValue"" = '{0}'",
                                                workItemType);
            }

            return workItemtypeClause.ToString();
        }

    }
}
